// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;

namespace SnapObjects.Data
{
    public interface IModelChangeTracker<TModel>
    {
        int Count(StateTrackable stateTrackable);

        void CancelTrack(TModel model);

        void Reset(ChangeTrackingStrategy changeTrackingStrategy);

        void ResetState(StateTrackable stateTrackable);

        ModelState GetModelState(TModel model);

        void SetModelState(TModel model, ModelState modelState);

        PropertyState GetPropertyState(TModel model, int propertyIndex);

        PropertyState GetPropertyState(TModel model, int propertyIndex, bool ignoreDefaultValue);

        void SetPropertyState(TModel model, int index, PropertyState propertyState);

        bool IsTracked(TModel model);

        TModel Track(IModelEntry<TModel> modelEntry);

        bool TrackDeleted(IList<TModel> models);

        bool TrackDeleted(TModel model);

        bool TrackNew(TModel model, bool modified = false);

        void TrackCheckOut(TModel model);

        void MarkPropertyModified(TModel model, int propertyIndex);

        void MarkAllPropertiesModified(TModel model);

        void MarkAllPropertiesNotModified(TModel model);

        bool TryGetOriginalValue(TModel model, int propertyIndex, out object value);

        bool TryGetOriginalValue(TModel model, string propertyName, out object value);

        bool TryGetOriginalValue<TValue>(TModel model, Func<TModel, TValue> selector, out TValue value);

        IList<ValidationResult> Validate(TModel model);

        IList<ValidationResult> ValidateAll();

        UpdateResult Update(
            DataContext dataContext,
            UpdateSqlStrategy updateSqlStrategy,
            UpdateWhereStrategy updateWhereStrategy,
            bool resetState = true);

        Task<UpdateResult> UpdateAsync(
           DataContext dataContext,
           UpdateSqlStrategy updateSqlStrategy,
           UpdateWhereStrategy updateWhereStrategy,
           bool resetState = true);

        Task<UpdateResult> UpdateAsync(
           DataContext dataContext,
           UpdateSqlStrategy updateSqlStrategy,
           UpdateWhereStrategy updateWhereStrategy,
           bool resetState,
           CancellationToken cancellationToken = default);

        void SyncModelStateFromProperties(TModel model);
    }
}
